#include "./../http_protocol_parser.h"

#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <gtest/gtest.h>
#include <vector>

TEST(ParserRequestLine, Line)
{
    std::string content = "GET /index.html HTTP/1.1\r\n";
    int         length  = 0;
    HttpRequest http_request;
    int         result =
        HttpProtocolUtil::ParseHttpProtocolLine((const uint8_t *)content.c_str(), content.size(), length, &http_request);
    EXPECT_EQ(1, result);
    length  = 0;
    content = "GET /index.html ";
    result =
        HttpProtocolUtil::ParseHttpProtocolLine((const uint8_t *)content.c_str(), content.size(), length, &http_request);
    EXPECT_EQ(0, result);
    content += "HTTP/1.1\r\n";
    result =
        HttpProtocolUtil::ParseHttpProtocolLine((const uint8_t *)content.c_str(), content.size(), length, &http_request);
    EXPECT_EQ(1, result);
    printf("content size : %ld and use length : %d.\n", content.size(), length);
}

TEST(ParserRequestSign, Sign)
{
    std::string                        sign_content = "Content-Type: text/html\r\nContent-Length: 100\r\n\r\n";
    HttpRequest                        http_request;
    int                                length = 0;
    std::map<std::string, std::string> sign_map;
    int result = HttpProtocolUtil::ParseHttpProtocolSign((const uint8_t *)sign_content.c_str(), sign_content.size(), length,
                                                         sign_map);
    EXPECT_EQ(1, result);
    printf("content size:%ld and use length:%d and map size:%ld.\n", sign_content.size(), length, sign_map.size());
    length = 0;
    sign_map.clear();
    sign_content = "Content-Type: text/html\r\nContent-Length: ";
    result = HttpProtocolUtil::ParseHttpProtocolSign((const uint8_t *)sign_content.c_str(), sign_content.size(), length,
                                                     sign_map);
    printf("content size:%ld and use length:%d and map size:%ld.\n", sign_content.size(), length, sign_map.size());
    EXPECT_EQ(0, result);
    sign_content       += "100\r\n\r\n";

    const uint8_t * ptr = (const uint8_t *)sign_content.c_str() + length;
    result              = HttpProtocolUtil::ParseHttpProtocolSign(ptr, sign_content.length(), length, sign_map);
    printf("content size:%ld and use length:%d and map size:%ld.\n", sign_content.size(), length, sign_map.size());
    EXPECT_EQ(1, result);
}

TEST(ParserRequestBody, Body)
{
    std::string content =
        "030000000000c61400000000020007636f6e6e656374003ff00000000000000300036170700200036170700008666c61736856657202000d4c4e5820392c302c3132342c320005746355726c02001d72746d703a2f2f382e3133342e3132332e3234363a313933352f6170700004667061640100000c6361706162696c697469657300402e00000000000000c30b617564696f436f646563730040afce0000000000000b766964656f436f6465637300406f800000000000000d766964656f46756e6374696f6e003ff0000000000000000009";
    std::vector<uint8_t> body;
    int                  length = 0;
    int result = HttpProtocolUtil::ParseHttpProtocolBody((const uint8_t *)content.c_str(), content.size(), length,
                                                         content.size(), body);
    EXPECT_EQ(result, 1);
    printf("body size : %ld and use length : %d.\n", body.size(), length);

    int size = (int)content.size();
    length   = 0;
    body.clear();
    result = HttpProtocolUtil::ParseHttpProtocolBody((const uint8_t *)content.c_str(), size - 100, length, size, body);
    printf("body size : %ld and use length : %d.\n", body.size(), length);
    EXPECT_EQ(result, 0);
    result =
        HttpProtocolUtil::ParseHttpProtocolBody((const uint8_t *)content.c_str() + (size - 100), 100, length, size, body);
    printf("body size : %ld and use length : %d.\n", body.size(), length);
    EXPECT_EQ(result, 1);
}

TEST(HexToDec, Number)
{
    std::string num    = "f";
    int         result = HttpProtocolUtil::HexToDec(num.c_str(), num.size());
    printf("result number : %d.\n", result);
}

TEST(ParseBodyChunk, Block)
{
    std::string          c = "10\r\n0123456789123456\r\n1\r\n1\r\n0\r\n\r\n";
    std::vector<uint8_t> body;
    int                  length = 0;
    int result = HttpProtocolUtil::ParseHttpProtocolChunk((const uint8_t *)c.c_str(), c.size(), length, body);
    printf("content size : %ld and use length : %d and body size : %ld.\n", c.length(), length, body.size());
    EXPECT_EQ(1, result);
    c      = "10\r\n1234567890\r\n10\r\n1234567890";
    length = 0;
    body.clear();
    result = HttpProtocolUtil::ParseHttpProtocolChunk((const uint8_t *)c.c_str(), c.size(), length, body);
    EXPECT_EQ(-1, result);
    c      = "10\r\n1234567890123456\r\n1\r\n\r\n111";
    length = 0;
    body.clear();
    result = HttpProtocolUtil::ParseHttpProtocolChunk((const uint8_t *)c.c_str(), c.size(), length, body);
    EXPECT_EQ(-1, result);

    c = "a\r\n0123456789\r\n5\r\n12345";
    body.clear();
    length = 0;
    result = HttpProtocolUtil::ParseHttpProtocolChunk((const uint8_t *)c.c_str(), c.size(), length, body);
    EXPECT_EQ(0, result);
    printf("length : %d and c size : %ld and body size : %ld.\n", length, c.size(), body.size());
    c     += "\r\n0\r\n\r\n";
    result = HttpProtocolUtil::ParseHttpProtocolChunk((const uint8_t *)c.c_str() + length, c.size(), length, body);
    EXPECT_EQ(1, result);
    printf("length : %d and c size : %ld and body size : %ld.\n", length, c.size(), body.size());
}

TEST(HttpResonseLine, Line)
{
    std::string  content = "HTTP/1.1 200 OK\r\n";
    HttpResponse response;
    int          length = 0;
    int          result =
        HttpProtocolUtil::ParseHttpProtocolLine((const uint8_t *)content.c_str(), content.size(), length, &response);
    printf("version:{%s},code:{%s},note:{%s}.\n", response.GetVersion().c_str(), response.GetCode().c_str(),
           response.GetNote().c_str());
    EXPECT_EQ(result, 1);
    printf("content size : %ld and use length : %d.\n", content.size(), length);
    length  = 0;
    content = "HTTP/1.1 204\r\n";
    result  = HttpProtocolUtil::ParseHttpProtocolLine((const uint8_t *)content.c_str(), content.size(), length, &response);
    printf("version:{%s},code:{%s},note:{%s}.\n", response.GetVersion().c_str(), response.GetCode().c_str(),
           response.GetNote().c_str());
    EXPECT_EQ(result, 1);
    printf("content size : %ld and use length : %d.\n", content.size(), length);
    content = "HTTP/1.1 200";
    length  = 0;
    result  = HttpProtocolUtil::ParseHttpProtocolLine((const uint8_t *)content.c_str(), content.size(), length, &response);
    EXPECT_EQ(result, 0);
    printf("version:{%s},code:{%s},note:{%s}.\n", response.GetVersion().c_str(), response.GetCode().c_str(),
           response.GetNote().c_str());
}

int main(int argc, char * argv[])
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
